#pragma once
#include "EngineHead.h"
#include "UnitDerive.h"
#include "Device.h"
#include "RenderNode.h"
#include "LightEffect.h"


#define RenderType1 (mini::RendererType::DeferredRenderer | \
					 mini::RendererType::FrontRenderer | \
					 mini::RendererType::ShadowRenderer | \
					 mini::RendererType::PostRenderer | \
					 mini::RendererType::ParticleRenderer | \
					 mini::RendererType::SkinRenderer)

namespace mini
{
	class CCamera;
	class CRenderViewport;
	class CRenderer
	{
		friend class CRendererEngine;
	public:
		explicit CRenderer(CDevice* pDevice);
		virtual ~CRenderer();
		const UINT32 getRendererOrder() const;
		const RendererType getRendererType() const;
		void setCamera(CCamera* pCamera);
		CCamera* getCamera() const;
		void setDevice(CDevice* pDevice);
		void setActive(bool bActive);
		void setEditor(bool bEditor);
		bool isActive();
		bool isEditor();
		void applyRenderNodes(std::set<CRenderNode*>* pRenderNodes);
		void applyPreRenderNodes();
		void executeRendererCommandList();
		void setDeviceContext(DeviceContext* pContext, int index);
		DeviceContext* getDeviceContext();
		int getDeviceContextIndex();
		void _render();
		void addEffect(CEffect* pEffect, int order);
		void removeEffect(CEffect* pEffect);

	protected:
		virtual void render();
		void addRenderViewPort(CRenderViewport* pViewPort);
		void removeRenderViewport(CRenderViewport* pViewport);
		virtual void processRenderNode(CRenderNode* pRenderNode);
		virtual void addUnit(CUnit* pUnit, CMaterialUnit* pMaterialUnit, EntityType Type, INT32 zLayer);
		virtual void clearAllUnit();
		virtual void commitToGpu();
		void addRenderNode(CRenderNode* pActor);
		void removeRenderNode(CRenderNode* pActor);
		void removeAllRenderNode();
		void updateLightToGpu();
		
	protected:
		int					mContextIndex = 0;
		DeviceContext*		mpDeferredContext = nullptr;
		RendererType		mRenderTypeFlag = RendererType::UnknowType;
		UINT32				mOrder;
		CCamera*			mpCamera;
		CDevice*			mpDevice;
		CLightEffect*		mpLightEffect = nullptr;
		std::map<CShaderUnit*, std::list<CMeshUnit*> >			mRenderUnits;
		std::map<CShaderUnit*, std::list<CMeshUnit*> >			mAlphaRenderUnits;
		std::map<INT32, std::pair< CShaderUnit*, CMeshUnit*> >	mZbufferOffRenderUnits;


		std::map<CShaderUnit*, std::list<CMeshUnit*> >			mRenderUnitsPoint;
		std::map<CShaderUnit*, std::list<CMeshUnit*> >			mAlphaRenderUnitsPoint;
		std::map<INT32, std::pair< CShaderUnit*, CMeshUnit*> >	mZbufferOffRenderUnitsPoint;

		std::list<CBoundBox* >	mRendererBoundBox;

		std::list<CLightActor*>	mLightActors;
		std::set<CRenderNode*>	mRenderNodes;
		std::set<CRenderNode*>*	mpCurrentRenderNodes = nullptr;
		std::set<CRenderNode*>*	mpPreRenderNodes = nullptr;
		std::list<CRenderViewport*>	mRenderViewports;
		bool				mbActive = true;
		bool				mbEditor = false;
		std::map<int, CEffect*>	mAttchEffects;
	};
}
